<template>
  <a-row>
    <a-col :span="$slots['addressBook']?6:0">
      <slot name="addressBook" v-if="$slots['addressBook']"></slot>
    </a-col>
    <a-col :span="$slots['addressBook']?18:24">
      <div ref="chatContentBox" class="chat-content-box">
        <div v-for="item in messageList" :key="item.text" style="padding: 10px;">
          <a-row>
            <a-col :span="12" :offset="item['type']==='sender' ? 12 : 0">
              <a-card :headStyle="item['type']==='sender'?senderStyle:askSenderStyle"
                      :bodyStyle="item['type']==='sender'?senderStyle:askSenderStyle">
                <template #title>
                  <div style="width:100%; display: flex;">
                    <span style="width:100%;">{{ item['username'] }}</span>
                    <span style="width: 100px;float:right;">{{ item['datetime'] }}</span>
                  </div>
                </template>
                <div v-if="item['isStream']" style="width:100%;height:42px;">
                  <a-spin tip="思考中..." style="width:100%;height:42px;">
                  </a-spin>
                </div>
                <VditorMarkdown v-else :content="item['content']"/>
              </a-card>

            </a-col>
          </a-row>
        </div>
      </div>
      <a-divider style="height: 1px;margin:4px  0"/>
      <div style="position:relative;">
        <a-textarea type="textarea" v-model:value="message" :rows="4" style="width: 100%" :bordered="false"
                    :placeholder="placeholder">
        </a-textarea>
        <a-button type="primary" style="position: absolute;right:0;bottom: 0;" @click="sendMsg"
                  :disabled="(!message)">
          发送
        </a-button>
      </div>
    </a-col>
  </a-row>
</template>
<script setup lang="ts">
import {ref} from "vue";
import {fetchEventSource} from "@microsoft/fetch-event-source";
import VditorMarkdown from "./VditorMarkdown.vue";

const props = defineProps({
  placeholder: {
    type: String,
    default: '请输入内容'
  },
  sendUserName: {
    type: String,
    default: '测试'
  },
  reviewUserName: {
    type: String,
    default: '只能问答'
  },
  type: {
    type: String,
    default: 'text'
  },
  deepSeek: {
    type: Object,
    default: {
      basicUrl: '',
      headers: {},
      params: {},
      method: 'post',
      queryKey: 'query',
      askKey: 'answer',
      docsKey: 'docs',
      markdown: false
    }
  },
  sendEvent: {
    type: Function,
    default: (v: string) => {
      console.log(v)
    }
  }
})

const senderStyle = ref({
  'line-height': '32px'
})

const askSenderStyle = ref({})
const message = ref<string>('')
const messageList = ref<any>([])
const chatContentBox = ref()
const sendMsg = () => {
  messageList.value.push({
    content: message.value,
    type: 'sender',
    username: props.sendUserName,
    datetime: getTime(),
    isStream: false
  })
  props.sendEvent(message.value);
  requestDeepSeek()
  scrollToBottom()
}
const abortController = ref<any>();
const currentAsk = ref<any>({
  content: '',
  type: 'ask',
  username: props.reviewUserName,
})
// 是否可以发送信息
const senderProject = ref(true)
const askIndex = ref(0)
const requestDeepSeek = async () => {
  try {
    messageList.value.push({
      ...currentAsk.value,
      datetime: getTime(),
      isStream: true
    })
    askIndex.value = messageList.value.length;
    senderProject.value = false
    let _mess = message.value
    message.value = ''
    abortController.value = new AbortController()
    docList.value = []
    await fetchEventSource("http://127.0.0.1:9090/demo/deepseek", {
      method: props.deepSeek.method,
      headers: props.deepSeek.headers,
      signal: abortController.value.signal,
      body: JSON.stringify({
        // ...props.deepSeek.params,
        // [props.deepSeek.queryKey]: _mess
        "ask":_mess
      }),
      async onopen(response: any) {
        if (response.status !== 200) {
          throw new Error(`请求失败: ${response.statusText}`);
        }
      },
      onmessage(msg: any) {
        if (msg.event === "FINAL_ANSWER") {
          // 处理最终结果
          finishAsk()
        } else {
          try {
            const parsed = JSON.parse(msg.data);
            console.log('msg.data', msg.data)
            updateStreamMessage(parsed);
          } catch (e) {
            console.error("消息解析失败:", e);
          }
        }
      },
      onclose() {
        console.log('连接关闭')
        finishAsk()
      },
      onerror(err) {
        console.error('连接错误', err)
      }
    })


  } catch
      (error) {
    console.error(error);
  }
}
const finishAsk = () => {
  let docText = "\n##### 参考文献"
  for (let i = 0; i<docList.value.length; i++) {
    docText += "- " + docList.value[i]['fileName'] + "\n"
  }
  messageList.value[askIndex.value - 1]['content'] += docText;
  console.log('*******************finishAsk')
  scrollToBottom()
}
const docList = ref([])
const updateStreamMessage = (jsonData: any) => {
  messageList.value[askIndex.value - 1]['isStream'] = false;
  messageList.value[askIndex.value - 1]['content'] += jsonData[props.deepSeek.askKey] || "";
  if (jsonData != null && jsonData[props.deepSeek.docsKey] && jsonData[props.deepSeek.docsKey].length > 0) {
    docList.value = docList.value.concat(jsonData[props.deepSeek.docsKey]);
  }
  if (jsonData != null) {
    console.log('*******************updateStreamMessage', jsonData[props.deepSeek.docsKey])
  }
  scrollToBottom()
}
const scrollToBottom = () => {
  if (chatContentBox.value) {
    chatContentBox.value.scrollTop = chatContentBox.value.scrollHeight;
  }
}
const getTime = () => {
  const now = new Date()
  return String(now.getHours()).padStart(2, '0') + ':' + String(now.getMinutes()).padStart(2, '0') + ":" + String(now.getSeconds()).padStart(2, '0')
}
</script>
<style>
.chat-content-box::-webkit-scrollbar {
  display: none;
}

.chat-content-box {
  height: 350px;
  max-height: 350px;
  overflow-y: scroll;
}

.chat-content-box .ant-card .ant-card-head {
  padding: 0 5px !important;
  line-height: 32px !important;
  min-height: 32px !important;
}

.chat-content-box .ant-card .ant-card-body {
  padding: 5px !important;
}
</style>